import javafx.animation.AnimationTimer;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image;
import javafx.scene.layout.Pane;



public class GameEngine {
    private final Canvas canvas;
    private final GraphicsContext gc;
    private AnimationTimer gameLoop;

    private final Player player;
    private final GameWorld gameWorld;
    private PauseScreenMenu pauseScreenMenu;

    private boolean gameOver = false;
    private Image bombIcon;
    private final Pane root;
    private static final double TARGET_FRAME_TIME = 1.0 / 180.0; // 180Hz的每帧时间(约5.56ms)
    private static final double FIXED_UPDATE_INTERVAL = 1.0 / 180.0; // 180Hz固定更新间隔
    private long lastUpdateTime = 0;
    private double accumulator = 0;



    public Player getPlayer() {
        return player;
    }

    public GameEngine(Canvas canvas, Pane root) {
        this.canvas = canvas;
        this.gc = canvas.getGraphicsContext2D();
        this.root = root;

        this.pauseScreenMenu = new PauseScreenMenu(this);

        // 加载炸弹图标
        try {
            bombIcon = new Image(getClass().getResourceAsStream("/images/bomb.png"));
        } catch (Exception e) {
            System.err.println("加载炸弹图标失败: " + e.getMessage());
        }

        // 初始化游戏世界和玩家
        this.player = new Player(100, GameConstants.getScreenHeight() - GameWorld.GRID_SIZE * (GameWorld.GROUND_ROWS + 1));
        this.gameWorld = new GameWorld(this.player);
    }

    public void startGame() {
        gameLoop = new AnimationTimer() {
            @Override
            public void handle(long now) {
                // 第一次调用初始化时间
                if (lastUpdateTime == 0) {
                    lastUpdateTime = now;
                    return;
                }

                // 计算经过的时间(秒)
                double deltaTime = (now - lastUpdateTime) / 1_000_000_000.0;
                lastUpdateTime = now;

                // 限制最大deltaTime避免卡顿时的"spiral of death"
                deltaTime = Math.min(deltaTime, 0.25);

                // 累积时间
                accumulator += deltaTime;

                // 固定时间步长更新
                while (accumulator >= FIXED_UPDATE_INTERVAL) {
                    if (!gameOver && !GameConstants.GAME_PAUSED) {
                        update(FIXED_UPDATE_INTERVAL);
                    }
                    accumulator -= FIXED_UPDATE_INTERVAL;
                }

                // 渲染(保持原有渲染逻辑)
                render();
            }
        };
        gameLoop.start();
    }

    public void togglePause() {
        GameConstants.GAME_PAUSED = !GameConstants.GAME_PAUSED;
    }

    public boolean isGamePaused() {
        return GameConstants.GAME_PAUSED;
    }

    private void update(double deltaTime) {
        // 应用游戏速度因子
        deltaTime *= GameConstants.GAME_SPEED;
        gameWorld.update(deltaTime);
        player.update(deltaTime, gameWorld);

        // 修改这部分代码
        if (gameWorld.isBossFightActive()) {
            if (gameWorld.getBoss().checkPlayerHit(player)) {
                if (player.hasShield()) {
                    player.setShieldHit(true);
                } else if (gameWorld.getBoss().isPlayerDefeated()) {
                    gameOver = true;  // 直接设置游戏结束
                    // 确保BOSS战结束逻辑执行
                    gameWorld.getBoss().deactivate();
                    gameWorld.setBossFightActive(false);
                }
            }
        }

        // 确保游戏结束状态被正确处理
        if (gameOver) {
            if (gameLoop != null) {
                gameLoop.stop();
            }
            return;
        }

        // 碰撞检测
        boolean wallCollision = gameWorld.checkWallCollision(player.getX(), player.getY(),
                player.getWidth(), player.getHeight());
        boolean batCollision = gameWorld.checkBatCollision(player.getX(), player.getY(),
                player.getWidth(), player.getHeight(), player.isSliding());

        if (wallCollision || batCollision) {
            if (player.hasShield() && !player.isShieldHit()) {
                player.setShieldHit(true); // 标记护盾被击中，但暂时保留护盾状态
            } else if (!player.isShieldHit()) { // 只有在不处于护盾被击中状态时才游戏结束
                gameOver = true;
            }
        }


        if (player.getY() > GameConstants.getScreenHeight()-40) {
            gameOver = true;
        }
    }


    private void render() {
        // 清除画布
        gc.clearRect(0, 0, GameConstants.getScreenWidth(), GameConstants.getScreenHeight());

        // 渲染游戏世界
        gameWorld.render(gc);

        // 渲染玩家
        player.render(gc);

        // 渲染UI
        renderUI();

        // 游戏结束画面
        if (gameOver) {
            renderGameOver();
            if (root.getChildren().contains(pauseScreenMenu)) {
                root.getChildren().remove(pauseScreenMenu);
            }
        }

        // 处理暂停画面
        if (GameConstants.GAME_PAUSED) {
            renderPauseScreen();
        } else {
            if (root.getChildren().contains(pauseScreenMenu)) {
                root.getChildren().remove(pauseScreenMenu);
            }
        }
    }

    private void renderPauseScreen() {
        if (!root.getChildren().contains(pauseScreenMenu)) {
            root.getChildren().add(pauseScreenMenu);
        }
    }




    private void renderUI() {
        int screenWidth = GameConstants.getScreenWidth();
        int screenHeight = GameConstants.getScreenHeight();

        // 设置字体大小，根据分辨率自适应
        double fontSize = Math.max(24, screenHeight * 0.04);
        gc.setFont(javafx.scene.text.Font.font("Arial", fontSize));
        gc.setFill(javafx.scene.paint.Color.WHITE);

        //显示玩家名字和分数
        String playerName = PlayerDataManager.loadPlayerName();
        if (playerName != null) {
            gc.fillText(" " + playerName, 20, 30);
        }
        gc.fillText("分数: " + gameWorld.getScore(), 20, playerName != null ? 60 : 30);


        // 显示炸弹数量和图标
        if (bombIcon != null) {
            // 计算炸弹图标大小（根据分辨率自适应）
            double iconSize = Math.max(30, screenHeight * 0.06);

            // 计算炸弹图标位置（右上角，留出边距）
            double iconX = screenWidth - iconSize - 20;
            double iconY = 20;

            // 绘制炸弹图标
            gc.drawImage(bombIcon, iconX, iconY, iconSize, iconSize);

            // 绘制炸弹数量（在图标下方）
            String bombText = "× " + player.getBombAcount();
            double textWidth = com.sun.javafx.tk.Toolkit.getToolkit().getFontLoader().computeStringWidth(bombText, gc.getFont());
            gc.fillText(bombText, iconX + (iconSize - textWidth)/2, iconY + iconSize + fontSize);
        }
    }

    private void renderGameOver() {
        if (gameWorld.getScore() > 0) {
            PlayerDataManager.saveScore(gameWorld.getScore());
        }
        gc.setFill(new javafx.scene.paint.Color(0, 0, 0, 0.6));
        double centerX = GameConstants.getScreenWidth() / 2;
        double centerY = GameConstants.getScreenHeight() / 2;
        gc.fillRect(0, 0, GameConstants.getScreenWidth(), GameConstants.getScreenHeight());

        gc.setFill(javafx.scene.paint.Color.WHITE);
        gc.setFont(javafx.scene.text.Font.font("微软雅黑", javafx.scene.text.FontWeight.BOLD, 48));
        String gameOverText = "游戏结束！";
        double textWidth = com.sun.javafx.tk.Toolkit.getToolkit().getFontLoader().computeStringWidth(gameOverText, gc.getFont());
        gc.fillText(gameOverText, centerX - textWidth/2, centerY - 50);

        gc.setFont(javafx.scene.text.Font.font("微软雅黑", javafx.scene.text.FontWeight.NORMAL, 24));
        String scoreText = "最终得分: " + gameWorld.getScore();
        textWidth = com.sun.javafx.tk.Toolkit.getToolkit().getFontLoader().computeStringWidth(scoreText, gc.getFont());
        gc.fillText(scoreText, centerX - textWidth/2, centerY);
        String restartText = "按 R 重新开始";
        textWidth = com.sun.javafx.tk.Toolkit.getToolkit().getFontLoader().computeStringWidth(restartText, gc.getFont());
        gc.fillText(restartText, centerX - textWidth/2, centerY + 50);

    }


    public void playerJump() {
        if (!player.isJumping()) {
            player.jump();
        }
    }

    public void resetGame() {
        // 停止游戏循环
        if (gameLoop != null) {
            gameLoop.stop();
            gameLoop = null;
        }

        // 重置游戏状态
        gameOver = false;
        gameWorld.setScore(0);
        gameWorld.reset();
        player.reset();
        GameConstants.GAME_PAUSED = false;
    }


    public boolean isPlayerJumping() {
        return player.isJumping();
    }

    public boolean isGameOver() {
        return gameOver;
    }


}